﻿/* ==============================================================================
*
*   Copyright (c) 2010, Pierre Favier
*   All rights reserved.
*
*   NTasking is free software: you can redistribute it and/or modify it
*   under the terms of the GNU General Public License as published by the
*   Free Software Foundation.
*
*   Redistribution and use in source and binary forms, with or without
*   modification, are permitted provided that the following conditions
*   are met:
*
*   -   Redistributions of source code must retain the above copyright notice,
*       this list of conditions and the following disclaimer.
*
*   -   Redistributions in binary form must reproduce the above
*       copyright notice, this list of conditions and the following
*       disclaimer in the documentation and/or other materials
*       provided with the distribution.
*
*   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
*   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
*   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
*   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
*   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
*   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
*   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
*   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
*   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
*   TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
*   THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
*   SUCH DAMAGE.
*
* ============================================================================== */

using System;
using NTasking;
using System.Threading;

namespace DiningPhilosophers
{

    public class Philosopher : Task
    {

        TableBase _table;
        int _id;
        int _eatTime;
        int _thinkTime;
        int _servings;


        private static readonly Action<Philosopher, TableBase, int, int, int> Initializer = (@this, table, id, eatTime, thinkTime) =>
        {
            @this._table = table;
            @this._id = id;
            @this._eatTime = eatTime;
            @this._thinkTime = thinkTime;
        };

        public Philosopher(TableBase table, int id, int eatTime, int thinkTime)
        {
            _table = table;
            _id = id;
            _eatTime = eatTime;
            _thinkTime = thinkTime;
        }


        protected override void Body()
        {
            while (!_table.GetBill())
            {
                if (!_table.Get[_id]())
                    _table.Wait[_id]();
                Thread.Sleep(_eatTime);
                _table.Put(_id);
                Thread.Sleep(_thinkTime);
                _servings += 1;
            }

            _table.Pay(_id, _servings, _eatTime * _servings, _thinkTime * _servings);
        }

    }


    //public class Philosopher : TaskType
    //{

    //    private readonly int _seat;
    //    private readonly Table _table;
    //    private readonly int _eatDelay;
    //    private readonly int _thinkDelay;
    //    private int _eatCount = 0;


    //    public Philosopher(Table table, int seat, int thinkDelay, int eatDelay)
    //    {
    //        _table = table;
    //        _seat = seat;
    //        _eatDelay = eatDelay;
    //        _thinkDelay = thinkDelay;
    //        Name = seat.ToString();
    //    }


    //    protected override void Body()
    //    {
    //        try
    //        {
    //            Tasking.select._
    //                (_table.WaitUntilClosed)().
    //            then_abort(() =>
    //            {
    //                while (true)
    //                {
    //                    Runtime.Delay(_thinkDelay);

    //                    _table.GetForks[_seat]();

    //                    _eatCount += 1;
    //                    Console.WriteLine(string.Format("Philosopher {0} is eating", _seat));

    //                    Runtime.Delay(_eatDelay);

    //                    _table.ReleaseForks(_seat);
    //                }
    //            }).
    //            end_select();

    //            Console.WriteLine(string.Format("{0} - {1} - {2} - has eaten {3} times", this, _eatDelay, _thinkDelay, _eatCount));
    //        }
    //        catch (Exception ex)
    //        {
    //            Console.WriteLine(this + " finished on exception " + ex.GetType().Name);
    //        }
    //    }

    //}

}
